unit uMainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,

  GlScene, GlObjects, GlCadencer, GLWin32Viewer, GLRenderContextInfo, GlWindowsFont, GlHudObjects,
  GlMaterial,
  VectorGeometry,
  uTweener,

  uDragManager;

type
  TfrmMain = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    {Main Objects}
    fGlScene: TGlScene;
    fCadencer: TGLCadencer;
    fViewer: TGLSceneViewer;
    fCamera: TGlCamera;
    fMainDummy: TGlDummyCube;
    fFpsTimer: Single;
    fMatLib: TGlMaterialLibrary;

    {Text Objects}
    fWinFont: TGLWindowsBitmapFont;
    fHudText: TGLHUDText;
    fBack: TGlHudSprite;

    fDragManager: TDragManager;
    fBasket: TDragTarget;

    MousePressed: Boolean;
  protected
    Procedure OnTargetChange(aManager: TDragManager; aDragObject: TDragObject; aDragTarget: TDragTarget; aPreviousTarget: TDragTarget);
    Procedure OnEndDrag(aManager: TDragManager; aDragObject: TDragObject; aDragTarget: TDragTarget; aPreviousTarget: TDragTarget);
  public
    Procedure InitFontAndSprites;
    Procedure InitMaterials;
    Procedure OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
  end;

var
  frmMain: TfrmMain;

implementation
uses
  glKeyboard,
  GLCrossPlatform,
  gltexture,
  uDemoInit;
{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  fFpsTimer := 0;
  CreateDemo(self, fGlScene, fCadencer, fViewer);
  
  fCamera := TGlCamera.CreateAsChild(fGlScene.Objects);
  with fCamera do
  begin
    Position.SetPoint(0, 0, 5);
    Direction.SetVector(0, 0, -1);
    Up.SetVector(0, 1, 0);
    CameraStyle := csOrthogonal;
    SceneScale := 0.1;
  end;

  fMainDummy := TGLDummyCube.CreateAsChild(fGlScene.Objects);
  fMainDummy.ObjectsSorting := osNone;

  fViewer.Camera := fCamera;
  fCadencer.OnProgress := OnCadencerProgress;

  fMatLib := TGlMaterialLibrary.Create(self);

  InitMaterials;
  InitFontAndSprites;
end;

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  fCadencer.Enabled := true;
end;

Procedure TfrmMain.OnTargetChange(aManager: TDragManager; aDragObject: TDragObject; aDragTarget: TDragTarget; aPreviousTarget: TDragTarget);
begin
end;

Procedure TfrmMain.OnEndDrag(aManager: TDragManager; aDragObject: TDragObject; aDragTarget: TDragTarget; aPreviousTarget: TDragTarget);
begin
  if aDragTarget = fBasket then
  begin
    aManager.DeleteByObject(aDragObject, true);
    aDragObject := nil;
  end;

  if (aDragObject <> nil) and (aDragObject.fSprite.Position.y < 80) then
    aManager.DeleteByObject(aDragObject, true);
end;

Procedure TfrmMain.InitFontAndSprites;
  Function AddCloneDragObject(aLeft, aTop: Single; aMatName: String; aPercents: Single): TDragObject;
  begin
    result := fDragManager.AddDragObject(VectorMake(aLeft, aTop, 0), aMatName);
    with result do
    begin
      Cloning := true;
      SetActionRect(-aPercents, -aPercents, aPercents, aPercents);
    end;
  end;
begin
  fWinFont := TGLWindowsBitmapFont.Create(self);
  fWinFont.Font.Name := 'Arial';

  fBack := TGlHudSprite.CreateAsChild(fMainDummy);
  with fBack do
  begin
    Material.LibMaterialName := 'back_1';
    Material.MaterialLibrary := fMatLib;
    Width := Material.GetActualPrimaryTexture.Image.Width;
    Height := Material.GetActualPrimaryTexture.Image.Height;
    Position.SetPoint(Width / 2, Height / 2, 0);
  end;

  fHudText := TGLHUDText.CreateAsChild(fMainDummy);
  with fHudText do
  begin
    BitmapFont := fWinFont;
    Text := 'Lampogolovii presents '+ #13#10 + '''DragAndDrop Demo''';
    ModulateColor.SetColor(1, 1, 1, 0.7);
    Position.SetPoint(5, 365, 0);
    Alignment := taLeftJustify;
  end;


  fDragManager := TDragManager.CreateAsChild(fMainDummy);
  fDragManager.Material.MaterialLibrary := fMatLib;

  fDragManager.AddDragTarget(VectorMake(300, 120, 0), 'dnd_item');
  fDragManager.AddDragTarget(VectorMake(170, 210, 0), 'dnd_item');
  fDragManager.AddDragTarget(VectorMake(430, 210, 0), 'dnd_item');
  fDragManager.AddDragTarget(VectorMake(250, 350, 0), 'dnd_item');
  fDragManager.AddDragTarget(VectorMake(350, 350, 0), 'dnd_item');
  fBasket := fDragManager.AddDragTarget(VectorMake(550, 350, 0), 'basket');

  AddCloneDragObject(50,  40,  'cup', 0.5);
  AddCloneDragObject(130, 40, 'key', 0.5);
  AddCloneDragObject(205, 40, 'sneakers', 0.5);
  AddCloneDragObject(290, 40, 'pillow', 0.5);
  AddCloneDragObject(380, 40, 'medkit', 0.5);
  AddCloneDragObject(470, 40, 'tooth', 0.5);
  AddCloneDragObject(550, 40, 'mittens', 0.5);

  fDragManager.OnEndDrag := OnEndDrag;
  fDragManager.OnDragProceedTarget := OnTargetChange;
end;

Procedure TfrmMain.InitMaterials;
begin
  AddMaterials(fMatLib, str_ImagesFolder + '\DragAndDrop\', ['back_1'], ['back_1']);
  AddMaterials(fMatLib, str_ImagesFolder + '\DragAndDrop\',
               ['cup', 'key', 'sneakers', 'dnd_item', 'pillow', 'basket', 'medkit', 'tooth', 'mittens'],
               ['cup', 'key', 'sneakers', 'dnd_item', 'pillow', 'basket', 'medkit', 'tooth', 'mittens']);
end;

Procedure TfrmMain.OnCadencerProgress(Sender : TObject; const deltaTime, newTime : Double);
var
  MPos: TPoint;
begin
  GetCursorPos(Mpos);
  MPos := fViewer.ScreenToClient(MPos);

  MousePressed := IsKeyDown(vk_LButton);

  fDragManager.SetMousePos(VectorMake(MPos.x, MPos.y, 0));
end;

end.

